/*******************************************************************************
*funtion: 
*date	:	
*author	:
*modify	:
*note	:
*******************************************************************************/
#include "PluginMgr.h"

#include "Poco/DirectoryIterator.h"
#include "Poco/File.h"
#include "Poco/Path.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/String.h"

#include "Poco/SingletonHolder.h"

using Poco::SingletonHolder;

using Poco::DirectoryIterator;
using Poco::File;

using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::icompare;


#define PLUGIN_EXT	"dll"

PluginMgr::PluginMgr()
{
}
PluginMgr::~PluginMgr()
{
	PluginMapIt it = m_PluginMap.begin();
	while (it!=m_PluginMap.end())
	{
		unload(it->first,it->second);
		it++;
	}
}

int PluginMgr::load(Path& path,PPluginLoader loader)
{
	try
	{
		loader.get()->loadLibrary(path.toString());
	}
	catch (Poco::Exception& exc)
	{
		std::cerr << "Invalid Plugin "<< exc.displayText() << std::endl;
		return -1;
	}
	std::cout << "LoadPlugin: "<< path.toString() << " OK!"<< std::endl;
	m_PluginMap.insert(make_pair(path.getFileName(),loader));

	return 0;
}
int PluginMgr::unload(const std::string& name,PPluginLoader loader)
{
	Path path;
	path.pushDirectory(m_DirPath);
	path.setFileName(name);
//	string tmp = path.toString();
	loader.get()->unloadLibrary(path.toString());

	return 0;
}

int PluginMgr::get(std::string& name,DevicePlugin* &pPlugin)
{
	std::string& classname = name;// + "Plugin";
	PluginMapIt it = m_PluginMap.begin();
	std::string pluginname = classname + "." + PLUGIN_EXT;
	it = m_PluginMap.find(pluginname);
	if (it!=m_PluginMap.end())
	{
		pPlugin = &it->second.get()->instance(classname);
		if (!pPlugin)
			return 0;
	}
	return -1;
}

int PluginMgr::init(std::string& dir)
{
	if (dir.empty())
		dir = Path::current();

	m_DirPath = dir;

	try
	{
		DirectoryIterator it(dir);
		DirectoryIterator end;
		while (it != end)
		{
			Path p(it->path());
			if (it->isDirectory())
			{
				++it;
				continue;
			}
			std::string& fext = p.getExtension();
			if (icompare(fext,PLUGIN_EXT)!=0)
			{
				++it;
				continue;
			}

			PPluginLoader pLoader(new PluginLoader);			
			load(p,pLoader);
			++it;
		}
	}
	catch (Poco::Exception& exc)
	{
		std::cerr << exc.displayText() << std::endl;
		return 1;
	}
		
	return 0;
}
int PluginMgr::fini()
{
	return 0;
}
namespace
{
	static SingletonHolder<PluginMgr> sh;
}
PluginMgr& PluginMgr::instance()
{
	return *sh.get();
}

